using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Domain.Interfaces.Repositories;
using SheLife.Infrastructure.Data;

namespace SheLife.Infrastructure.Repositories
{
    public class MenstrualCycleRepository : Repository<MenstrualCycle>, IMenstrualCycleRepository
    {
        public MenstrualCycleRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<MenstrualCycle> GetByUserIdAndDateAsync(Guid userId, DateTime date)
        {
            return await _dbSet
                .Where(m => m.UserId == userId && m.Date.Date == date.Date)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<MenstrualCycle>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Where(m => m.UserId == userId && m.Date >= startDate && m.Date <= endDate)
                .OrderBy(m => m.Date)
                .ToListAsync();
        }

        public async Task<MenstrualCycle> GetLatestByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(m => m.UserId == userId)
                .OrderByDescending(m => m.Date)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<MenstrualCycle>> GetByCycleTypeAsync(Guid userId, string cycleType)
        {
            return await _dbSet
                .Where(m => m.UserId == userId && m.CycleType == cycleType)
                .OrderBy(m => m.Date)
                .ToListAsync();
        }
    }

    public class MenstrualSymptomRepository : Repository<MenstrualSymptom>, IMenstrualSymptomRepository
    {
        public MenstrualSymptomRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<MenstrualSymptom>> GetByCycleIdAsync(Guid cycleId)
        {
            return await _dbSet
                .Where(m => m.MenstrualCycleId == cycleId)
                .ToListAsync();
        }

        public async Task<IEnumerable<MenstrualSymptom>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Include(m => m.MenstrualCycle)
                .Where(m => m.MenstrualCycle.UserId == userId && m.MenstrualCycle.Date >= startDate && m.MenstrualCycle.Date <= endDate)
                .OrderBy(m => m.MenstrualCycle.Date)
                .ToListAsync();
        }

        public async Task<IEnumerable<MenstrualSymptom>> GetBySymptomTypeAsync(Guid userId, string symptomType)
        {
            return await _dbSet
                .Include(m => m.MenstrualCycle)
                .Where(m => m.MenstrualCycle.UserId == userId && m.SymptomType == symptomType)
                .OrderBy(m => m.MenstrualCycle.Date)
                .ToListAsync();
        }
    }

    public class MenstrualNoteRepository : Repository<MenstrualNote>, IMenstrualNoteRepository
    {
        public MenstrualNoteRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<MenstrualNote>> GetByCycleIdAsync(Guid cycleId)
        {
            return await _dbSet
                .Where(m => m.MenstrualCycleId == cycleId)
                .ToListAsync();
        }

        public async Task<IEnumerable<MenstrualNote>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Include(m => m.MenstrualCycle)
                .Where(m => m.MenstrualCycle.UserId == userId && m.MenstrualCycle.Date >= startDate && m.MenstrualCycle.Date <= endDate)
                .OrderBy(m => m.MenstrualCycle.Date)
                .ToListAsync();
        }
    }

    public class BasalBodyTemperatureRepository : Repository<BasalBodyTemperature>, IBasalBodyTemperatureRepository
    {
        public BasalBodyTemperatureRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<BasalBodyTemperature>> GetByUserIdAndDateRangeAsync(Guid userId, DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Where(b => b.UserId == userId && b.Date >= startDate && b.Date <= endDate)
                .OrderBy(b => b.Date)
                .ToListAsync();
        }

        public async Task<BasalBodyTemperature> GetLatestByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(b => b.UserId == userId)
                .OrderByDescending(b => b.Date)
                .FirstOrDefaultAsync();
        }
    }
}